import java.util.ArrayList;

public abstract class Pet {
	
	
	public Pet(Pet another) { 
	    this.name = another.name;
		this.description = another.description;
		this.element = another.element;
		this.currentXP = another.currentXP;
		this.damageTaken = another.damageTaken;
		this.defense = another.defense;
		this.strength = another.strength;
		this.speed = another.speed;
		this.size = another.size; //1-10 där 1 är tiny och 50 är massive
		this.attacks = another.attacks;
		this.frontImage = another.frontImage;
		this.backImage = another.backImage;
	  }
	
	public Pet(String petName, String petDescription, Type petElement, int petXP, int petDamageTaken, int petDef, int petStr, int petSpd, int petSize,ArrayList<AttackName> petAttacks, String petFrontImage, String petBackImage){
		name = petName;
		description = petDescription;
		element = petElement;
		currentXP = petXP;
		damageTaken = petDamageTaken;
		defense = petDef;
		strength = petStr;
		speed = petSpd;
		size = petSize; //1-10 där 1 är tiny och 50 är massive
		attacks.addAll(petAttacks);
		frontImage=petFrontImage;
		backImage=petBackImage;
		
		
	}
	public Pet(String petName, String petDescription, Type petElement, int petXP, int petDef, int petStr, int petSpd, int petSize, ArrayList<AttackName> attacks, String petFrontImage, String petBackImage){
		name = petName;
		this.attacks.addAll(attacks);
		currentXP = petXP;
		int level = getCurrentLevel();
		if(petSize<170){
			description = petDescription;
			element = petElement;
			currentXP = petXP;
			damageTaken = 0;
			defense = petDef + level*3;
			size = petSize + level*6; //1-10 där 1 är tiny och 50 är massive
			speed = (int) (petSpd + level*8 - size*0.005);
			strength = (int) (petStr + level*3 + size*0.1);
			frontImage=petFrontImage;
			backImage=petBackImage;
			
		}
		else if (petSize>349){
			description = petDescription;
			element = petElement;
			currentXP = petXP;
			damageTaken = 0;
			defense = petDef + level*7;
			size = petSize + level*12; //1-10 där 1 är tiny och 50 är massive
			strength = (int) (petStr + level*7 + size*0.1);
			speed = (int) (petSpd + level*3 - size*0.005);
			frontImage=petFrontImage;
			backImage=petBackImage;
		}
		
		else{
		description = petDescription;
		element = petElement;
		currentXP = petXP;
		damageTaken = 0;
		defense = petDef + level*5;
		size = petSize + level*9; //1-10 där 1 är tiny och 50 är massive
		strength = (int) (petStr + level*5 + size*0.1);
		speed = (int) (petSpd + level*6 - size*0.005);
		frontImage=petFrontImage;
		backImage=petBackImage;
		}
		
	}
	
	
	public Pet() {}


	public double energy = 0;
	protected String name;
	protected String description;
	protected String backImage;
	protected String frontImage;
	protected Type element;
	protected int currentXP = 90;
	protected int damageTaken;
	
	protected ArrayList<AttackName> attacks = new ArrayList<AttackName>();
	
	protected int defense;
	protected int strength;
	protected int speed;
	protected int size;
	public static int exp = -1;
	
	abstract public Pet copy();
	abstract public Pet copy(int lol);
	
	public abstract ArrayList<AttackName> startingAttacks(int exp);
	
	public String getName() {
		return name;
	}
	
	public String getDescription() {
		return description;
	}	
	
	public Type getPetElement() {
		return element;
	}
	
	public int getCurrentXP() {
		return currentXP;
	}
	
	public int getDamageTaken() {
		return damageTaken;
	}
	
	public int getStrength() {
		return strength;
	}
	
	public int getDefense() {
		return defense;
	}
	
	public int getSpeed() {
		return speed;
	}
	
	public int getSize() {
		return size;
	}
	
	public ArrayList<AttackName> getAttacks() {
		return attacks;
	}
	
	public boolean isAlive() {
		return damageTaken < getMaxHealth();
	}
	
	public void increaseEnergy(){
		
		energy = energy + 0.025*(speed/(10.0+(getCurrentLevel()-1)/6.0));
	}

	public int getlevelUpXP() {
		int levelUpXP = 100 + (getCurrentLevel() - 1)*100;
		return levelUpXP;
	}
	
	//baserar level p� m�ngden XP
	public int getCurrentLevel() {
		return ((currentXP/100) + 1);
	}
	
	public int getMaxHealth() {
		int maxHealth = 50 + getCurrentLevel()*10 + 5*defense;
		return maxHealth;
	}
	
	public int getCurrentHealth() {
		int currentHealth = getMaxHealth() - damageTaken;
		return currentHealth;
	}
	
	public void levelingUp(int str, int def, int spd, int petSize) {
		
		if(petSize<170){
			defense = def + 4;
			size = petSize + 7; //1-10 där 1 är tiny och 50 är massive
			speed = (int) (spd + 9 - size*0.005);
			strength = (int) (str + 4 + size*0.01);
		}
		else if (petSize>349){
			defense = def + 8;
			size = petSize + 13; //1-10 där 1 är tiny och 50 är massive
			strength = (int) (str + 8 + size*0.01);
			speed = (int) (spd + 4 - size*0.005);
		}
		
		else{
		defense = def + 6;
		size = petSize + 10; //1-10 där 1 är tiny och 50 är massive
		strength = (int) (str + 6 + size*0.01);
		speed = (int) (spd + 7 - size*0.005);
		}
		
	}
		
	public AttackName checkNewAttack(int level, Type element){
		switch (level) {
		/* natur */
		case 2:
			if(element == Type.Nature){
				return AttackName.Vissla;
			}
			if(element == Type.Energy){
				return AttackName.Förödmjuka;
			}
			if(element == Type.Fire){
				return AttackName.Eldrustning;
			}
			if(element == Type.Water){	
				return AttackName.VattenIÖgat;
			}
		/* energi */
		case 4:
			if(element == Type.Nature){
				return AttackName.Äggning;	
			}
			if(element == Type.Energy){
				return AttackName.Skalla;
			}
			if(element == Type.Fire){
				return AttackName.Eldslag;
			}
			if(element == Type.Water){
				return AttackName.VattenKanon;
			}
			
		/* vatten */
		case 6:
			if(element == Type.Nature){
				return AttackName.NaturTillstånd;
			}
			if(element == Type.Energy){
				return AttackName.BiffKrim;	
			}
			if(element == Type.Fire){
				return AttackName.Rökridå;
			}
			if(element == Type.Water){
				return AttackName.Bubbelpool;
			}
		
			
		/* eld */
		case 8:
			if(element == Type.Nature){
				return AttackName.BrorteinFjärt;
			}
			if(element == Type.Energy){
				return AttackName.Blixtsnabb;
			}
			if(element == Type.Fire){
				return AttackName.EldIllussion;
			}
			if(element == Type.Water){
				return AttackName.Strömvirvel;
			}
			break;
		
		case 10:
			if(element == Type.Nature){
				return AttackName.HagelStorm;
			}
			if(element == Type.Energy){
				return AttackName.Elkretsanalys;
			}
			if(element == Type.Fire){
				return AttackName.Pungspark;
			}
			if(element == Type.Water){
				return AttackName.Tsunami;
			}
		}
		return null;	
		
	}
	
	/*
	 * Ska returnera en sträng som berättar vad som händer
	 * tex vid level up ska den säga "blabla leveled up!"
	 */
	public boolean gainXP (int gainedXP){
		//�ka XP. TODO: Level-up check.
		int upXP = getlevelUpXP();
		currentXP = currentXP + gainedXP;
		if (currentXP == upXP )
		return true;
		else 
		return false;
	}
	//L�gg till attack
	public void addAttack(AttackName newAttack) {
		if (attacks.contains(newAttack) == false && attacks.size() < 4 && new Attack(newAttack).type == this.element ){
			attacks.add(newAttack);
		}
		/** Do we need this?
		else {
			throw new RuntimeException(this.name + " already has that attack or has reached maximum attacks known");
		}**/
	}
	
	//Ta bort attack
	public void removeAttack(AttackName attackName) {
		
		if (attacks.contains(attackName) == true){
			attacks.remove(attackName);
		}
		else throw new RuntimeException(this.name + " does not have that attack");
	}
	
}
